package com.yunji.system.aspectj;

import com.yunji.common.annotation.DataScope;
import com.yunji.common.annotation.DataScopeThread;
import com.yunji.common.base.SqlConcatParam;
import com.yunji.common.base.SqlConcatParamThread;
import com.yunji.common.enums.common.PermissionTypeEnum;
import com.yunji.common.model.dto.LoginInfo;
import com.yunji.common.utils.bean.BeanUtils;
import com.yunji.system.context.SystemContext;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.NamedThreadLocal;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.Arrays;
import java.util.List;

/**
 * @author : peter-zhu
 * @date : 2024/11/20 16:57
 * @description : TODO
 **/
@Aspect
@Component
@Order(5)
public class SqlConditionAspect {
    public static final ThreadLocal<DataScopeThread> DATA_SCOPE_THREAD = new NamedThreadLocal<>("DataScopeThread");

    public static final ThreadLocal<SqlConcatParamThread> SQL_PARAM_THREAD = new NamedThreadLocal<>("SqlParamThread");

    @Pointcut(value = "((execution(* com.yunji.*.dao.*.*(..)) || execution(* com.yunji.*.mapper.*.*(..))) && @annotation(dataScope))")
    public void daoAndMapperPoint(DataScope dataScope) {
    }

    //@Before("execution(* com.yunji.*.dao.*.*(..)) || execution(* com.yunji.*.mapper.*.*(..))")
    @Before(value = "daoAndMapperPoint(dataScope)", argNames = "joinPoint,dataScope")
    public void daoAndMapperMethods(JoinPoint joinPoint, DataScope dataScope) {
        boolean hasParam = dataScope.hasParam();
        if (hasParam) {
            Object[] args = joinPoint.getArgs();
            for (Object arg : args) {
                if (arg instanceof SqlConcatParam) {
                    SqlConcatParam sqlParam = (SqlConcatParam) arg;
                    SqlConcatParamThread spt = new SqlConcatParamThread();
                    spt.setChildren(dataScope.children());
                    spt.setPermissionTypes(dataScope.value());
                    spt.setExcludeTables(dataScope.excludeTables());
                    spt.setScopeTables(dataScope.scopeTables());
                    spt.setDeep(dataScope.deep());
                    spt.setParam(sqlParam.getParam());
                    List<PermissionTypeEnum> requestTypes = PermissionTypeEnum.getRequestTypes(dataScope.value());
                    spt.setPermissionTypeList(requestTypes);
                    if (!CollectionUtils.isEmpty(spt.getPermissionTypeList()) && spt.getParam() != null) {
                        SQL_PARAM_THREAD.set(spt);
                    }
                    break;
                }
            }
        }
        LoginInfo loginUser = SystemContext.getUser();
        if (BeanUtils.isNotNull(loginUser)) {
            // 如果是超级管理员，则不过滤数据
            if (BeanUtils.isNotNull(loginUser) && !loginUser.isAdmin()) {
                System.out.println("非管理员,开始拦截注解数据");
                DataScopeThread dst = new DataScopeThread();
                dst.setChildren(dataScope.children());
                dst.setPermissionTypes(dataScope.value());
                dst.setExcludeTables(dataScope.excludeTables());
                dst.setScopeTables(dataScope.scopeTables());
                dst.setDeep(dataScope.deep());
                DATA_SCOPE_THREAD.set(dst);
            }
        }
    }

    @After(value = "daoAndMapperPoint(dataScope)", argNames = "dataScope")
    public void doAfterReturning(DataScope dataScope) {
        SQL_PARAM_THREAD.remove();
        DATA_SCOPE_THREAD.remove();
    }
}
